A decision tree classifies by asking a sequence of questions, which makes it the most directly interpretable model in this course: the path from root to leaf is the explanation. This chapter covers how a tree chooses those questions, and where the approach runs out of road.
We work through the anatomy of a tree, the top-down greedy CART training procedure, and the impurity measures — Gini and entropy — that drive split selection, including a full hand calculation of a root split. We then handle continuous features via threshold splits, and the stopping criteria and regularisation hyperparameters that keep a tree from memorising its training set. The chapter closes with the geometric view: a single tree carves the feature space into axis-aligned rectangles, and that limitation is precisely the motivation for the ensembles that follow.
Learning Objectives
Describe the anatomy of a decision tree and read a prediction as a rule path
Compute Gini impurity and entropy, and select a root split by information gain
Handle continuous features by evaluating candidate threshold splits
Control overfitting with max_depth, min_samples_leaf and related hyperparameters
Explain the axis-aligned rectangle geometry of a tree and the limitation it imposes
Compare decision trees against KNN and Naive Bayes across interpretability, speed and assumptions
2. Theory
2.1 Decision Tree Anatomy
A decision tree predicts by routing an observation down a sequence of if/else tests, starting at the root and ending at a leaf. The leaf reached determines the predicted class, and the tests along the path form a rule that explains the prediction.
s*
2.2 Top-Down Greedy Training (CART Algorithm)
DT learning is a top-down, recursive, binary-split, greedy procedure:
Start with all \(N\) training samples at the root node.
Find the best split (feature, threshold) that maximizes the weighted decrease in impurity (Gini or Entropy).
Partition the node's data into left/right children using that split.
Recurse on each child until a stopping criterion fires (depth limit, pure node, min samples, etc.).
Each leaf predicts the majority class (classification) or mean value (regression).
2.3 Impurity Measures
To choose a split we need a way to measure how mixed the classes are in a node. Two measures are in common use, and they behave similarly in practice:
Gini Index (CART)
Entropy + IG (ID3/C4.5)
Side-by-Side
\[
G(D) = 1 - \sum_{i=1}^{k} p_i^2
\]
Here \(p_i\) is the proportion of class \(i\) in node \(D\). The Gini index ranges from \(0\) for a pure node to \( \frac{k-1}{k}\) when the \(k\) classes are mixed in equal proportions.
IG = reduction in entropy caused by the split. Range of \(H\): 0 (pure) → \(\log_2 k\) (max). We maximize IG; equivalently, we minimize weighted child entropy.
Property
Gini
Entropy
Computation
Faster (squares, no log)
Slower (\(\log_2\) per class)
Range (binary)
\([0, 0.5]\)
\([0, 1]\) bit
Algorithm family
CART (scikit-learn default)
ID3 / C4.5 / C5.0
Empirical difference
Typically produces very similar trees. Entropy can help with severe class imbalance.
2.4 Hand Calculation — Choose the Root Split (Play Golf, Gini)
Parent (root): 9 Yes, 5 No → \(G_{\text{root}} = 1 - (9/14)^2 - (5/14)^2 = 1 - 0.413 - 0.128 = 0.459\).
Compute weighted Gini for splitting on each of the 4 categorical features:
Feature →
Outlook
Temperature
Humidity
Windy
Child Gini (weighted)
5/14·G(S) + 4/14·G(O) + 5/14·G(R)
4/14·G(Ht)+6/14·G(Md)+4/14·G(Cl)
7/14·G(Hi)+7/14·G(Nm)
8/14·G(F)+6/14·G(T)
Compute
5/14·0.48 + 4/14·0 + 5/14·0.48
4/14·0.50+6/14·0.44+4/14·0.375
7/14·0.490 + 7/14·0.245
8/14·0.375+6/14·0.50
Weighted Gini
0.3429 ← Best (lowest)
0.4405
0.3675
0.4286
✅ Root-Split Winner
Outlook reduces parent impurity from 0.459 → 0.343, the largest drop of all 4 candidate features.
CART therefore makes Outlook the root split. Repeat the same calculation independently on each child to grow deeper.
2.5 Continuous (Numerical) Features — Threshold Splits
For a continuous feature \(X\), sort its unique values, evaluate the midpoint between every pair as a candidate split
\(X \le t\) vs. \(X > t\), and pick the \(t\) giving the lowest weighted child Gini.
Left to run, the recursion continues until every leaf is pure, which produces a tree that has memorized the training set. The following hyperparameters stop the growth early and control this:
Hyperparameter
What it does
Typical default / tuning range
max_depth
Stop growing once tree reaches this depth. Main control vs overfit.
None (unlimited); try {3, 5, 8, 12, 20}
min_samples_split
Minimum samples in a node before it is eligible for splitting.
2 (default); try {2, 5, 10, 20}
min_samples_leaf
Minimum samples that must land in each resulting leaf.
1 (default); try {1, 3, 5, 10}
max_features
Number of features to randomly subset at each split (Random Forests).
{"sqrt", "log2", d, 0.3·d}
ccp_alpha (pruning)
Cost-complexity pruning. Higher α → aggressively prune small branches post-hoc.
0.0; search via path
2.7 DT vs. kNN vs. NB — Grand Comparison
With three classifiers now covered, it is useful to compare them on the practical points that decide which one to reach for:
Dimension
kNN (k=5)
Naive Bayes
Decision Tree (depth 5)
Scaling required?
✅ YES (critical for distance)
Depends (Gaussian yes, MNB no)
❌ NO (invariant to monotonic scaling)
Handles interactions?
Implicitly via distance
❌ No (independence)
✅ Yes (hierarchical splits)
Interpretability
Low (black-box distances)
Medium (odds ratios)
✅ High (if/then rules, feature_importances_)
Categorical features
Needs OHE/Gower
✅ Native (MultinomialNB)
OHE or ordinal (HistGradientBoosting native)
Prediction latency
Slow O(n·d)
Fast O(d)
Fast O(depth)
Overfitting risk
Low (kNN is stable)
✅ Very low (high bias)
High (unlimited depth → memorizes)
2.8 Geometric Interpretation of DTs — Axis-Aligned Rectangles
Credit-risk toy example: 30 loan applicants (16 default, 14 non-default). Features: Age, Account Balance ($).
A shallow DT learns two splits:
\(\text{Balance} \ge 50{,}000\)? (vertical line)
Else \(\text{Age} \ge 45\)? (horizontal line in the left half-plane)
s*
Single-DT Geometric Limitations
Cannot express diagonal or curved decision boundaries (e.g., lines of form \(x_1 + x_2 \le t\) require many splits).
High variance: swap a few training points → the rectangle corners move → boundary changes a lot.
Solutions: (a) use many DTs and average them (Random Forest smoothes the boundary), (b) use kernel/boosting variants.
3. Interactive Examples
Example 1: Gini & Entropy Calculations
A node contains 60 class-A samples and 40 class-B samples.
Step 3: Both splits tie in weighted Gini (0.333). Both give a decrease of 0.375 − 0.333 = 0.042.
A tie-breaking rule (lower index feature / leftmost threshold) picks one.
Problem 2: Effect of max_depth on Overfitting
You train two trees on Adult Census (26K train rows):
Tree A (max_depth = 3) → train-AUC 0.86, test-AUC 0.855.
Tree B (max_depth = None, unlimited) → train-AUC 0.998, test-AUC 0.84.
📘 Diagnostics & fix
Diagnosis: Tree A = healthy low-bias/moderate-variance fit (tiny 0.005 train–test gap).
Tree B = severe overfitting: train AUC near-perfect, test AUC worse than Tree A by 1.5 points.
Fix: Limit capacity via one or more of:
Reduce max_depth (GridSearch {2..10}) — single strongest lever.
Increase min_samples_leaf to {5, 10, 20} so leaves can't memorize small pockets.
Apply Cost-Complexity Pruning (tune ccp_alpha).
OR: move to an ensemble (Random Forest / Gradient Boosting) — they solve DT overfitting architecturally (next units!).
Problem 3: Feature Importances from Split Counts
A small tree has 5 splits total: feature A used 3 times (weighted Gini decreases of 0.40, 0.30, 0.10),
feature B used 2 times (decreases 0.25, 0.05), feature C never used. Compute normalized feature importances.
📘 Step-by-Step
Total decrease = (0.40+0.30+0.10) + (0.25+0.05) + 0 = 1.10.
Importances: A = 0.80/1.10 ≈ 72.7 %, B = 0.30/1.10 ≈ 27.3 %, C = 0 %.
(These sum to 1.0. scikit-learn normalizes the total impurity decrease exactly this way.)
5. Try It Yourself
Problem 1 — Gini for 3 Classes
Node has classes {A:5, B:3, C:2}. Compute Gini impurity.
\(G = 1 - (0.5)^2 - (0.3)^2 - (0.2)^2 = 1 - (0.25+0.09+0.04) = 1 - 0.38 = \mathbf{0.62}\).
(Max possible Gini for k=3 is \(2/3 \approx 0.667\) — this node is close to uniform mixing.)
Problem 2 — Weighted Child Gini (2-Way Split)
Split a 20-sample parent into Left (12 samples: 10 pos, 2 neg) and Right (8 samples: 1 pos, 7 neg).
Compute weighted Gini of the split and compare it to parent G = 0.48. Did purity improve? By how much?
GL = 1 − (10/12)² − (2/12)² ≈ 0.278; GR = 1 − (1/8)² − (7/8)² ≈ 0.219.
Weighted Gini = 0.6·0.278 + 0.4·0.219 ≈ 0.254.
Purity improved by 0.480 − 0.254 = 0.226 (large drop → good split!).
Problem 3 — Overfitting Diagnosis
Tree-C has max_depth=10, min_samples_leaf=1. Its train accuracy = 0.998 but test accuracy = 0.712 on the same task as Problem 2 of §4.
(i) What is this phenomenon? (ii) Name 3 knobs to fix it.
(i) Severe overfitting (memorization of training-set noise).
(ii) Any three valid regularizers from: lower max_depth, higher min_samples_leaf, higher min_samples_split, max_features (if ensembling), ccp_alpha cost-complexity pruning, early stopping, switching to a Random Forest / Gradient Boosting ensemble.
6. Interactive Quiz
Answer all 6 questions. Click an option for instant feedback.
Your score: 0 / 6
7. Key Takeaways
CART = Top-down greedy binary splits. At each node, sweep every (feature, threshold) pair; keep the one minimizing weighted child Gini (Entropy, MSE, MAE for regression).
Gini vs. Entropy rarely produce materially different trees. Gini is faster default; Entropy/IG can help with heavy imbalance or when using information-theoretic justifications.
Numeric features → try every midpoint as threshold and pick the best binary split (X ≤ t vs. > t). This is why DTs are scale-invariant: only the order matters.
DTs overfit unless you regularize. Unlimited-depth DTs memorize noise. The single most effective lever: max_depth. Combine with min_samples_leaf and optionally ccp_alpha pruning.
D strengths: No scaling, native handling of mixed types (with OHE or HistGBT), interpretable rules, built-in feature importances, fast prediction. Weakness: high variance → unstable trees. Solution: ensembles!
Grand comparison: NB fastest/baseline & text king; kNN simplest lazy distance method; DTs best for rule-based interpretability and strong tabular baselines. Enemies of DT: deep unlimited trees, tiny leaf samples.
8. Common Pitfalls
Training unlimited-depth DTs on default scikit-learn settings. This almost always overfits. Always set max_depth at a minimum.
Using Gini / Entropy on regression trees. For regression, split on MSE / MAE reduction — not Gini. scikit-learn's DecisionTreeRegressor does this.
Dropping feature names / not plotting the tree. DTs are interpretable by design — leverage this! Use tree.plot_tree or export_graphviz.
One-hot encoding high-cardinality categorical features into a deep CART tree. This creates imbalanced splits and blows up depth. Use HistGradientBoostingClassifier's categorical_features or target encoding instead.
Believing feature_importances_ measure causal importance. They measure correlation-driven impurity reduction on the training set. Two correlated features can split credit arbitrarily. Use permutation importance + SHAP for robust interpretations.
Comparing DT (single) against a tuned ensemble and concluding "trees are bad." Single trees are the weak learner. The power of DTs is as base learners inside Random Forest / Gradient Boosting.